use crate::src::struct_and_type::{
    Set, SetEntry, SetEqualFunc, SetFreeFunc, SetHashFunc, SetIterator, SetValue,
};

extern "C" {
    fn malloc(_: u64) -> *mut ();
    fn calloc(_: u64, _: u64) -> *mut ();
    fn free(_: *mut ());
}
static mut set_primes: [u32; 24] = [ 193 as u32, 389 as u32, 769 as u32, 1543 as u32, 3079 as u32, 6151 as u32, 12289 as u32, 24593 as u32, 49157 as u32, 98317 as u32, 196613 as u32, 393241 as u32, 786433 as u32, 1572869 as u32, 3145739 as u32, 6291469 as u32, 12582917 as u32, 25165843 as u32, 50331653 as u32, 100663319 as u32, 201326611 as u32, 402653189 as u32, 805306457 as u32, 1610612741 as u32,
];
static mut set_num_primes: u32 = 0;
extern "C" fn set_allocate_table(mut set: *mut Set) -> i32 {
    if (unsafe { (*set).prime_index }) < (unsafe { set_num_primes }) {
        (unsafe { (*set).table_size = set_primes[(*set).prime_index as usize] });
    } else {
        (unsafe { (*set).table_size = ((*set).entries).wrapping_mul(10 as i32 as u32) });
    }
    (unsafe {
        (*set).table = calloc(
            (*set).table_size as u64,
            ::core::mem::size_of::<*mut SetEntry>() as u64,
        ) as *mut *mut SetEntry
    });
    return ((unsafe { (*set).table }) != core::ptr::null_mut() as *mut *mut SetEntry) as i32;
}
extern "C" fn set_free_entry(mut set: *mut Set, mut entry: *mut SetEntry) {
    if unsafe { ((*set).free_func).is_some() } {
        (unsafe { ((*set).free_func).expect("non-null function pointer")((*entry).data) });
    }
    (unsafe { free(entry as *mut ()) });
}
#[no_mangle]
pub extern "C" fn set_new(mut hash_func: SetHashFunc, mut equal_func: SetEqualFunc) -> *mut Set {
    let mut new_set: *mut Set = 0 as *mut Set;
    new_set = (unsafe { malloc(::core::mem::size_of::<Set>() as u64) }) as *mut Set;
    if new_set.is_null() {
        return 0 as *mut Set;
    }
    (unsafe { (*new_set).hash_func = hash_func });
    (unsafe { (*new_set).equal_func = equal_func });
    (unsafe { (*new_set).entries = 0 as u32 });
    (unsafe { (*new_set).prime_index = 0 as u32 });
    (unsafe { (*new_set).free_func = None });
    if set_allocate_table(new_set) == 0 {
        (unsafe { free(new_set as *mut ()) });
        return 0 as *mut Set;
    }
    return new_set;
}
#[no_mangle]
pub extern "C" fn set_free(mut set: *mut Set) {
    let mut rover: *mut SetEntry = 0 as *mut SetEntry;
    let mut next: *mut SetEntry = 0 as *mut SetEntry;
    let mut i: u32 = 0;
    i = 0 as u32;
    while i < (unsafe { (*set).table_size }) {
        rover = unsafe { *((*set).table).offset(i as isize) };
        while !rover.is_null() {
            next = unsafe { (*rover).next };
            set_free_entry(set, rover);
            rover = next;
        }
        i = i.wrapping_add(1);
        i;
    }
    (unsafe { free((*set).table as *mut ()) });
    (unsafe { free(set as *mut ()) });
}
#[no_mangle]
pub extern "C" fn set_register_free_function(mut set: *mut Set, mut free_func: SetFreeFunc) {
    (unsafe { (*set).free_func = free_func });
}
extern "C" fn set_enlarge(mut set: *mut Set) -> i32 {
    let mut rover: *mut SetEntry = 0 as *mut SetEntry;
    let mut next: *mut SetEntry = 0 as *mut SetEntry;
    let mut old_table: *mut *mut SetEntry = 0 as *mut *mut SetEntry;
    let mut old_table_size: u32 = 0;
    let mut old_prime_index: u32 = 0;
    let mut index: u32 = 0;
    let mut i: u32 = 0;
    old_table = unsafe { (*set).table };
    old_table_size = unsafe { (*set).table_size };
    old_prime_index = unsafe { (*set).prime_index };
    (unsafe { (*set).prime_index = ((*set).prime_index).wrapping_add(1) });
    (unsafe { (*set).prime_index });
    if set_allocate_table(set) == 0 {
        (unsafe { (*set).table = old_table });
        (unsafe { (*set).table_size = old_table_size });
        (unsafe { (*set).prime_index = old_prime_index });
        return 0;
    }
    i = 0 as u32;
    while i < old_table_size {
        rover = unsafe { *old_table.offset(i as isize) };
        while !rover.is_null() {
            next = unsafe { (*rover).next };
            index =
                (unsafe { ((*set).hash_func).expect("non-null function pointer")((*rover).data) })
                    .wrapping_rem(unsafe { (*set).table_size });
            (unsafe { (*rover).next = *((*set).table).offset(index as isize) });
            let fresh0 = unsafe { &mut (*((*set).table).offset(index as isize)) };
            *fresh0 = rover;
            rover = next;
        }
        i = i.wrapping_add(1);
        i;
    }
    (unsafe { free(old_table as *mut ()) });
    return 1;
}
#[no_mangle]
pub extern "C" fn set_insert(mut set: *mut Set, mut data: SetValue) -> i32 {
    let mut newentry: *mut SetEntry = 0 as *mut SetEntry;
    let mut rover: *mut SetEntry = 0 as *mut SetEntry;
    let mut index: u32 = 0;
    if (unsafe { (*set).entries })
        .wrapping_mul(3 as i32 as u32)
        .wrapping_div(unsafe { (*set).table_size })
        > 0 as u32
    {
        if set_enlarge(set) == 0 {
            return 0;
        }
    }
    index = (unsafe { ((*set).hash_func).expect("non-null function pointer")(data) })
        .wrapping_rem(unsafe { (*set).table_size });
    rover = unsafe { *((*set).table).offset(index as isize) };
    while !rover.is_null() {
        if (unsafe { ((*set).equal_func).expect("non-null function pointer")(data, (*rover).data) })
            != 0
        {
            return 0;
        }
        rover = unsafe { (*rover).next };
    }
    newentry = (unsafe { malloc(::core::mem::size_of::<SetEntry>() as u64) }) as *mut SetEntry;
    if newentry.is_null() {
        return 0;
    }
    (unsafe { (*newentry).data = data });
    (unsafe { (*newentry).next = *((*set).table).offset(index as isize) });
    let fresh1 = unsafe { &mut (*((*set).table).offset(index as isize)) };
    *fresh1 = newentry;
    (unsafe { (*set).entries = ((*set).entries).wrapping_add(1) });
    (unsafe { (*set).entries });
    return 1;
}
#[no_mangle]
pub extern "C" fn set_remove(mut set: *mut Set, mut data: SetValue) -> i32 {
    let mut rover: *mut *mut SetEntry = 0 as *mut *mut SetEntry;
    let mut entry: *mut SetEntry = 0 as *mut SetEntry;
    let mut index: u32 = 0;
    index = (unsafe { ((*set).hash_func).expect("non-null function pointer")(data) })
        .wrapping_rem(unsafe { (*set).table_size });
    rover = (unsafe { &mut *((*set).table).offset(index as isize) }) as *mut *mut SetEntry;
    while !(unsafe { *rover }).is_null() {
        if (unsafe {
            ((*set).equal_func).expect("non-null function pointer")(data, (**rover).data)
        }) != 0
        {
            entry = unsafe { *rover };
            (unsafe { *rover = (*entry).next });
            (unsafe { (*set).entries = ((*set).entries).wrapping_sub(1) });
            (unsafe { (*set).entries });
            set_free_entry(set, entry);
            return 1;
        }
        rover = unsafe { &mut (**rover).next };
    }
    return 0;
}
#[no_mangle]
pub extern "C" fn set_query(mut set: *mut Set, mut data: SetValue) -> i32 {
    let mut rover: *mut SetEntry = 0 as *mut SetEntry;
    let mut index: u32 = 0;
    index = (unsafe { ((*set).hash_func).expect("non-null function pointer")(data) })
        .wrapping_rem(unsafe { (*set).table_size });
    rover = unsafe { *((*set).table).offset(index as isize) };
    while !rover.is_null() {
        if (unsafe { ((*set).equal_func).expect("non-null function pointer")(data, (*rover).data) })
            != 0
        {
            return 1;
        }
        rover = unsafe { (*rover).next };
    }
    return 0;
}
#[no_mangle]
pub extern "C" fn set_num_entries(mut set: *mut Set) -> u32 {
    return unsafe { (*set).entries };
}
#[no_mangle]
pub extern "C" fn set_to_array(mut set: *mut Set) -> *mut SetValue {
    let mut array: *mut SetValue = 0 as *mut SetValue;
    let mut array_counter: i32 = 0;
    let mut i: u32 = 0;
    let mut rover: *mut SetEntry = 0 as *mut SetEntry;
    array = (unsafe {
        malloc((::core::mem::size_of::<SetValue>() as u64).wrapping_mul((*set).entries as u64))
    }) as *mut SetValue;
    if array.is_null() {
        return 0 as *mut SetValue;
    }
    array_counter = 0;
    i = 0 as u32;
    while i < (unsafe { (*set).table_size }) {
        rover = unsafe { *((*set).table).offset(i as isize) };
        while !rover.is_null() {
            let fresh2 = unsafe { &mut (*array.offset(array_counter as isize)) };
            *fresh2 = unsafe { (*rover).data };
            array_counter += 1;
            array_counter;
            rover = unsafe { (*rover).next };
        }
        i = i.wrapping_add(1);
        i;
    }
    return array;
}
#[no_mangle]
pub extern "C" fn set_union(mut set1: *mut Set, mut set2: *mut Set) -> *mut Set {
    let mut iterator: SetIterator = SetIterator {
        set: 0 as *mut Set,
        next_entry: 0 as *mut SetEntry,
        next_chain: 0,
    };
    let mut new_set: *mut Set = 0 as *mut Set;
    let mut value: SetValue = core::ptr::null_mut();
    new_set = set_new(unsafe { (*set1).hash_func }, unsafe { (*set1).equal_func });
    if new_set.is_null() {
        return 0 as *mut Set;
    }
    set_iterate(set1, &mut iterator);
    while set_iter_has_more(&mut iterator) != 0 {
        value = set_iter_next(&mut iterator);
        if set_insert(new_set, value) == 0 {
            set_free(new_set);
            return 0 as *mut Set;
        }
    }
    set_iterate(set2, &mut iterator);
    while set_iter_has_more(&mut iterator) != 0 {
        value = set_iter_next(&mut iterator);
        if set_query(new_set, value) == 0 {
            if set_insert(new_set, value) == 0 {
                set_free(new_set);
                return 0 as *mut Set;
            }
        }
    }
    return new_set;
}
#[no_mangle]
pub extern "C" fn set_intersection(mut set1: *mut Set, mut set2: *mut Set) -> *mut Set {
    let mut new_set: *mut Set = 0 as *mut Set;
    let mut iterator: SetIterator = SetIterator {
        set: 0 as *mut Set,
        next_entry: 0 as *mut SetEntry,
        next_chain: 0,
    };
    let mut value: SetValue = core::ptr::null_mut();
    new_set = set_new(unsafe { (*set1).hash_func }, unsafe { (*set2).equal_func });
    if new_set.is_null() {
        return 0 as *mut Set;
    }
    set_iterate(set1, &mut iterator);
    while set_iter_has_more(&mut iterator) != 0 {
        value = set_iter_next(&mut iterator);
        if set_query(set2, value) != 0 {
            if set_insert(new_set, value) == 0 {
                set_free(new_set);
                return 0 as *mut Set;
            }
        }
    }
    return new_set;
}
#[no_mangle]
pub extern "C" fn set_iterate(mut set: *mut Set, mut iter: *mut SetIterator) {
    let mut chain: u32 = 0;
    (unsafe { (*iter).set = set });
    (unsafe { (*iter).next_entry = 0 as *mut SetEntry });
    chain = 0 as u32;
    while chain < (unsafe { (*set).table_size }) {
        if !(unsafe { *((*set).table).offset(chain as isize) }).is_null() {
            (unsafe { (*iter).next_entry = *((*set).table).offset(chain as isize) });
            break;
        } else {
            chain = chain.wrapping_add(1);
            chain;
        }
    }
    (unsafe { (*iter).next_chain = chain });
}
#[no_mangle]
pub extern "C" fn set_iter_next(mut iterator: *mut SetIterator) -> SetValue {
    let mut set: *mut Set = 0 as *mut Set;
    let mut result: SetValue = core::ptr::null_mut();
    let mut current_entry: *mut SetEntry = 0 as *mut SetEntry;
    let mut chain: u32 = 0;
    set = unsafe { (*iterator).set };
    if (unsafe { (*iterator).next_entry }).is_null() {
        return core::ptr::null_mut();
    }
    current_entry = unsafe { (*iterator).next_entry };
    result = unsafe { (*current_entry).data };
    if !(unsafe { (*current_entry).next }).is_null() {
        (unsafe { (*iterator).next_entry = (*current_entry).next });
    } else {
        (unsafe { (*iterator).next_entry = 0 as *mut SetEntry });
        chain = (unsafe { (*iterator).next_chain }).wrapping_add(1 as i32 as u32);
        while chain < (unsafe { (*set).table_size }) {
            if !(unsafe { *((*set).table).offset(chain as isize) }).is_null() {
                (unsafe { (*iterator).next_entry = *((*set).table).offset(chain as isize) });
                break;
            } else {
                chain = chain.wrapping_add(1);
                chain;
            }
        }
        (unsafe { (*iterator).next_chain = chain });
    }
    return result;
}
#[no_mangle]
pub extern "C" fn set_iter_has_more(mut iterator: *mut SetIterator) -> i32 {
    return ((unsafe { (*iterator).next_entry }) != core::ptr::null_mut() as *mut SetEntry) as i32;
}
extern "C" fn run_static_initializers_set() {
    (unsafe {
        set_num_primes = (::core::mem::size_of::<[u32; 24]>() as u64)
            .wrapping_div(::core::mem::size_of::<i32>() as u64) as u32
    });
}
#[used]
#[cfg_attr(target_os = "linux", link_section = ".init_array")]
#[cfg_attr(target_os = "windows", link_section = ".CRT$XIB")]
#[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
static INIT_ARRAY: [unsafe extern "C" fn(); 1] = [run_static_initializers_set];
